﻿// <copyright file="Orifice.cs" company="City of Portland, BES-ASM">
// </copyright>
// <summary>Orifice class</summary>

namespace BESASM.EMGAATS.BusinessClasses
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;

  /// <summary>
  /// Orifice class
  /// </summary>
  public class Orifice : Entity, IOrifice
  {
    private string name;
    private INode usNode;
    private INode dsNode;
    private ILink toLink;
    private OrificeOrientation orientation;
    private double area;
    private double coefficient;
    private OrificeShape shape;
    private double offset;

    /// <summary>
    /// Initializes a new instance of the <see cref="Orifice"/> class
    /// </summary>
    /// <param name="id">The ID of the Orifice</param>
    public Orifice(int id)
      : base(EntityType.Orifice, id)
    {
    }

    /// <summary>
    /// Gets or sets the name of the orifice
    /// </summary>
    public string OrificeName
    {
      get
      {
        return this.name;
      }

      set
      {
        if (value != this.name)
        {
          this.name = value;
          this.NotifyPropertyChanged();
        }
      }
    }

    /// <summary>
    /// Gets or sets the upstream node of the orifice
    /// </summary>
    public INode USNode 
    {
      get
      {
        return this.usNode;
      }

      set
      {
        if (value != this.usNode)
        {
          this.usNode = value;
          this.NotifyPropertyChanged();
        }
      }
    }

    /// <summary>
    /// Gets or sets the downstream node of the orifice
    /// </summary>
    public INode DSNode
    {
      get
      {
        return this.dsNode;
      }

      set
      {
        if (value != this.dsNode)
        {
          this.dsNode = value;
          this.NotifyPropertyChanged();

          if (this.dsNode != null)
          {
            this.ToLink = null;
          }
        }
      }
    }

    /// <summary>
    /// Gets or sets the downstream link of the weir
    /// </summary>
    public ILink ToLink
    {
      get
      {
        return this.toLink;
      }

      set
      {
        if (value != this.toLink)
        {
          this.toLink = value;
          this.NotifyPropertyChanged();

          if (this.toLink != null)
          {
            this.DSNode = null;
          }
        }
      }
    }

    /// <summary>
    /// Gets or sets the orientation of the orifice; <see cref="OrificeOrientation"/>
    /// </summary>
    public OrificeOrientation Orientation
    {
      get
      {
        return this.orientation;
      }

      set
      {
        if (value != this.orientation)
        {
          this.orientation = value;
          this.NotifyPropertyChanged();
        }
      }
    }

    /// <summary>
    /// Gets or sets the area of the orifice, in square feet
    /// </summary>
    public double AreaSqFt 
    {
      get
      {
        return this.area;
      }

      set
      {
        if (value != this.area)
        {
          this.area = value;
          this.NotifyPropertyChanged();
        }
      }
    }

    /// <summary>
    /// Gets or sets the coefficient of the orifice
    /// </summary>
    public double Coefficient
    {
      get
      {
        return this.coefficient;
      }

      set
      {
        if (value != this.coefficient)
        {
          this.coefficient = value;
          this.NotifyPropertyChanged();
        }
      }
    }

    /// <summary>
    /// Gets or sets the shape of the orifice
    /// </summary>
    public OrificeShape OrificeShape 
    {
      get
      {
        return this.shape;
      }

      set
      {
        if (value != this.shape)
        {
          this.shape = value;
          this.NotifyPropertyChanged();
        }
      }
    }

    /// <summary>
    /// Gets or sets the invert offset of the orifice from the node invert in feet
    /// </summary>
    public double InvertOffsetFt
    {
      get
      {
        return this.offset;
      }

      set
      {
        if (value != this.offset)
        {
          this.offset = value;
          this.NotifyPropertyChanged();
        }
      }
    }

    /// <summary>
    /// Gets a value indicating whether orifice has a ToLink specified
    /// </summary>
    public bool HasToLink
    {
      get
      {
        return this.ToLink != null;
      }
    }

    /// <summary>
    /// Creates a new orifice that is a copy of the current instance
    /// </summary>
    /// <returns>A new orifice that is a shallow copy of this instance</returns>
    public override object Clone()
    {
      // Simple properties and references
      // DO NOT copy Network, clones must be added to a network
      Orifice clone = new Orifice(this.Id);

      clone.AreaSqFt = this.AreaSqFt;
      clone.Coefficient = this.Coefficient;
      clone.DSNode = this.DSNode;
      clone.InvertOffsetFt = this.InvertOffsetFt;
      clone.Orientation = this.Orientation;
      clone.OrificeShape = this.OrificeShape;
      clone.ToLink = this.ToLink;
      clone.USNode = this.USNode;
      clone.OrificeName = this.OrificeName;

      this.CloneAuditProperties(clone);

      clone.SetModified(false);
      return clone;
    }

    /// <summary>
    /// Returns a string representation of this orifice
    /// </summary>
    /// <returns>The string representation of this orifice</returns>
    public override string ToString()
    {
      if (this.DSNode != null)
      {
        return string.Format(
          "O{0}/{3} (N{1}-N{2})", 
          this.Id, 
          this.USNode == null ? 0 : this.USNode.Id, 
          this.DSNode.Id,
          this.OrificeName);
      }
      else if (this.ToLink != null)
      {
        return string.Format(
          "O{0}/{3} (N{1}-L{2})", 
          this.Id,
          this.USNode == null ? 0 : this.USNode.Id, 
          this.ToLink.Id, 
          this.OrificeName);
      }
      else
      {
        return string.Format(
          "O{0}/{2} (N{1}-)", 
          this.Id,
          this.USNode == null ? 0 : this.USNode.Id, 
          this.OrificeName);
      }
    }
  }
}
